package handler

import (
	"errors"
	"log"
	"moft/database"
	"moft/model"
	"net/http"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type AuthHandler struct {
	db *gorm.DB
}

func NewAuthHandler() *AuthHandler {
	return &AuthHandler{db: database.DB()}
}

func (h *AuthHandler) Login(c *gin.Context) {
	var payload struct {
		UserName string `json:"user_name" binding:"required"`
		Password string `json:"password" binding:"required"`
	}
	if err := c.ShouldBindJSON(&payload); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error":   "the request body message error",
			"message": err.Error(),
		})
		return
	}

	// find user.
	user, err := model.FindUserByNamePass(h.db, payload.UserName, payload.Password)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": "the user name or password error",
			})
			return
		}
		log.Printf("find user by username %s failed: %v", user.UserName, err)
		c.Status(http.StatusInternalServerError)
		return
	}

	// build session
	values := map[string]interface{}{
		"user_id":   user.ID,
		"user_name": user.UserName,
		"is_admin":  user.RoleName == model.AdminRoleName,
	}
	sess := model.NewSession(c.Request).SetValues(values)
	if err := sess.Save(c.Writer, c.Request); err != nil {
		log.Printf("save session values failed: %v", err)
		c.Status(http.StatusInternalServerError)
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"user": user,
	})
}

func (h *AuthHandler) Logout(c *gin.Context) {
	sess := model.NewSession(c.Request).DeleteAll()
	if err := sess.Save(c.Writer, c.Request); err != nil {
		log.Printf("save session values failed: %v", err)
		c.Status(http.StatusInternalServerError)
		return
	}

	c.Status(http.StatusNoContent)
}
